package jp.co.ziro.wikidozan.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Logger;
import java.util.regex.Matcher;

import jp.co.ziro.wikidozan.model.View;
import jp.co.ziro.wikidozan.service.ViewService;


import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;

public abstract class BaseController extends Controller {

    @SuppressWarnings("unused")
    private static final Logger logger = Logger.getLogger(IndexController.class.getName());
    private static final String HOME_PAGE = "Main Page";

    @Override
    public Navigation run() throws Exception {

        String uri = request.getRequestURI();
        logger.info(uri);

        Properties parms = new Properties();
        int qmi = uri.indexOf( '?' );
        if ( qmi >= 0 ) {
            decodeParms( uri.substring( qmi+1 ), parms );
            uri = decodePercent( uri.substring( 0, qmi ));
        }

        UriPath path = new UriPath(uri);
        Request requestData = new Request(path, parms);

        String id = requestScope("pageId");
        if ( id == null ) {
            id = HOME_PAGE;
        } else {
            id = id.replaceAll("\\$", "");
        	id = id.trim();
        }

       	requestData.getPath().setId(id);

        ControllerResponse conResponse = createResponse(requestData);
        write(conResponse, path);

        return null;
    }

    protected abstract ControllerResponse createResponse(Request requestData) throws Exception;
    
    private static final String CONTENT_MATCHER = "@content@";

    /**
     * Loads the view for the specific controller and action and embeds the
     * controllers resulting xml.
     * 
     * @param response
     * @return
     */
    private void write(ControllerResponse responseData, UriPath path) {
       
        String controller = responseData.getController();
        if ( controller == null ) {
            controller = "wiki";
        }

        String viewName = "./public/views/" + controller + "/"
                + responseData.getTemplate() + ".xml";
        logger.info(viewName);

        ViewService service = new ViewService();

        View viewTxt = service.findView(viewName);
        StringBuffer buffer = new StringBuffer(viewTxt.getText());

        String fullData = buffer.toString().replaceFirst(CONTENT_MATCHER,
                    Matcher.quoteReplacement(responseData.getXml().toString()));


        try {
            response.setContentType("text/xml;charset=utf-8");
            PrintWriter out = response.getWriter();
            out.println(fullData);
            out.close();
  
        } catch (IOException e) {
            e.printStackTrace();
        }
        return;
    }


    /**
     * Decodes parameters in percent-encoded URI-format ( e.g.
     * "name=Jack%20Daniels&pass=Single%20Malt" ) and adds them to given
     * Properties.
     */
    private void decodeParms( String parms, Properties p )
        throws InterruptedException
    {
        if ( parms == null )
            return;

        StringTokenizer st = new StringTokenizer( parms, "&" );
        while ( st.hasMoreTokens())
        {
            String e = st.nextToken();
            int sep = e.indexOf( '=' );
            if ( sep >= 0 )
                p.put( decodePercent( e.substring( 0, sep )).trim(),
                       decodePercent( e.substring( sep+1 )));
        }
    }
    
    /**
     * Decodes the percent encoding scheme. <br/>
     * For example: "an+example%20string" -> "an example string"
     */
    protected String decodePercent( String str ) throws InterruptedException
    {
        try
        {
            return decodePercentHelper(str);
        }
        catch( Exception e )
        {
            return null;
        }
    }
    protected static String decodePercentHelper(String str) throws UnsupportedEncodingException {
        return URLDecoder.decode(str, "UTF-8");
    }
}
